﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using SiteParser.Core.Logging;
using System.Threading;
using SiteParser.Core.Configuration;

namespace SiteParser.Core.Utilites
{
	public static class HttpUrlResolver
	{
		private const int requestTimeOut = 5000;
		private const int maxConnectionAttemptCount = 10;

		public static Stream ResolveReference(string url) {
			return ResolveReference(url, ParserConfigSection.Instance.CacheConfig.ReadCacheEnabled, ParserConfigSection.Instance.CacheConfig.WriteCacheEnabled);
		}

		public static Stream ResolveReference(string url, bool readCacheEnabled, bool writeCacheEnabled) {
			if (string.IsNullOrEmpty(url)) {
				throw new ArgumentNullException("url");
			}

			url = url.Replace("&amp;", "&");

			if (readCacheEnabled && ResponseCacheManager.IsCached(url)) {
				return ResponseCacheManager.GetCachedResponseStream(url);
			}
			else {
				bool responseRecieved = false;
				int connectionAttemptCount = 0;

				HttpWebResponse response = null;

				while (!responseRecieved && connectionAttemptCount < maxConnectionAttemptCount) {
					try {
						Logger.Info(string.Format("Attempt No {0}: Getting content from '{1}'...", connectionAttemptCount + 1, url));
						HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(url);
						webRequest.ContentType = "text/html";
						response = (HttpWebResponse)webRequest.GetResponse();
						responseRecieved = true;
						Logger.Info("Content is recieved.");
					}
					catch (Exception exc) {
						Logger.Warning(string.Format("Unable to recieve a response. {0}", exc));
						connectionAttemptCount++;
						Logger.Info(string.Format("Wait {0}ms before next operation.", requestTimeOut));
						Thread.Sleep(requestTimeOut);
					}
				}

				if (response != null) {
					if (writeCacheEnabled) {
						ResponseCacheManager.CacheResponse(url, response);
						response.Close();
						return ResponseCacheManager.GetCachedResponseStream(url);
					}
					else {
						return response.GetResponseStream();
					}
				}

				return null;
			}
		}

		public static TextReader ResolveTextReference(string url, string encodingName) {
			return ResolveTextReference(url, encodingName, 
				ParserConfigSection.Instance.CacheConfig.ReadCacheEnabled, 
				ParserConfigSection.Instance.CacheConfig.WriteCacheEnabled);
		}

		public static TextReader ResolveTextReference(string url, string encodingName, bool readCacheEnabled, bool writeCacheEnabled) {
			Stream responseStream = ResolveReference(url, readCacheEnabled, writeCacheEnabled);
			return responseStream != null ? new StreamReader(responseStream, Encoding.GetEncoding(encodingName)) : null;
		}

		public static string GetReferenceStringContent(string url, string encodingName, bool readCacheEnabled, bool writeCacheEnabled) {
			TextReader responseStreamReader = ResolveTextReference(url, encodingName, readCacheEnabled, writeCacheEnabled);
			if (responseStreamReader != null) {
				using (TextReader reader = responseStreamReader) {
					return reader.ReadToEnd();
				}
			}
			else {
				return null;
			}
		}

		public static string GetReferenceStringContent(string url, string encodingName) {
			return GetReferenceStringContent(url, encodingName,
				ParserConfigSection.Instance.CacheConfig.ReadCacheEnabled,
				ParserConfigSection.Instance.CacheConfig.WriteCacheEnabled);
		}

		public static string CombineUrls(string currentUrl, string destUrl) {
			bool isDestUrlValid;

			try {
				Uri destUri = new Uri(destUrl);
				isDestUrlValid = true;
			}
			catch {
				isDestUrlValid = false;
			}

			return isDestUrlValid ? destUrl : new Uri(new Uri(currentUrl), destUrl).AbsoluteUri;
		}
		
	}
}
